#include "StatusCode.h"

using namespace std;

/** Constructeur par défaut.
 * Permet de construire un StatusCode avec ses différents champs.
 *
 * @param etat \e true ou \e false, suivant la réussite ou l'échec
 * d'une méthode (par défaut \e true).
 * @param val valeur de renvoi de la fonction (par défaut, 0).
 * @param code valeur du code d'erreur (par défaut, 0).
 * @param message valeur du message que l'on veut propager (par défaut
 * "").
 */
StatusCode::StatusCode(const bool& etat, const int& val, const int& code,
	     const string& message)
  : Etat( etat ), Code( code ), Message( message )
{
  Valeurs.push_back( val );
}

/** Constructeur par défaut.
 * Permet de construire un StatusCode avec ses différents champs.
 *
 * @param etat \e true ou \e false, suivant la réussite ou l'échec
 * d'une méthode.
 * @param val valeurs de renvoi de la fonction.
 * @param code valeur du code d'erreur (par défaut, 0).
 * @param message valeur du message que l'on veut propager (par défaut
 * "").
 */
StatusCode::StatusCode(const bool& etat,  const vector< int >& val,
		       const int& code, const string& message)
  : Etat( etat ), Code( code ), Message( message )
{
  Valeurs.assign( val.begin(), val.end() );
}

/** Constructeur de copie
 * Permet de réaliser une copie proprement d'un StatusCode.
 *
 * @param sc StatusCode à copier.
 */
StatusCode::StatusCode(const StatusCode& sc)
  : Etat( sc.Etat ), Code( sc.Code ), Message( sc.Message )
{
  Valeurs.assign( sc.Valeurs.begin(), sc.Valeurs.end() );
}

/**
 * Destructeur, ne fait rien de spécial.
 */
StatusCode::~StatusCode()
{}

/**
 * Permet de convertir un StatusCode en bool, afin de pouvoir écrire
 * simplement :
 * @code
 * StatusCode sc( maFonction );
 *
 * if ( sc )
 * { ... }
 * @endcode
 *
 * L'opérateur renvoie simplement la valeur du champ Etat.
 */
StatusCode::operator bool() const
{
  return Etat;
}

/**
 * Permet de convertir un StatusCode en int. L'opérateur renvoie alors
 * la valeur du champ Valeur.
 */
StatusCode::operator int() const
{
  return Valeurs.front();
}

/**
 * Permet d'accéder au champ Etat.
 *
 * @return Etat.
 */
const bool& StatusCode::etat() const
{
  return Etat;
}

/**
 * Permet d'accéder au champ Valeur. Lors de l'utilisation par défaut,
 * il n'y a qu'une seule valeur. Sinon il faut spécifier l'indice par
 * argument.
 *
 * @param num indice de la valeur voulue.
 * @return une référence constante sur la valeur du champ voulu, si
 * l'indice est trop grand, alors on renvoie la \e dernière valeur.
 */
const int& StatusCode::valeur(const unsigned int& num) const
{
  if ( num >= Valeurs.size() )
    return Valeurs.back();
  else
    return Valeurs[ num ];
}

/**
 * Permet d'accéder au champ Code.
 *
 * @return Code.
 */
const int& StatusCode::code() const
{
  return Code;
}

/**
 * Permet d'accéder au champ Message.
 *
 * @return Message.
 */
const string& StatusCode::message() const
{
  return Message;
}

/**
 * Permet de récupérer le nombre de valeurs renvoyées.
 *
 * @return la taille du conteneur Valeurs.
 */
unsigned int StatusCode::nombre() const
{
  return Valeurs.size();
}

ostream& operator<<(ostream& os, const StatusCode& sc)
{
  if ( sc.nombre() == 1 )
    os << "Valeur : " << sc.valeur() << ", Code : " << sc.code() << ", "
       << sc.message();
  else
    {
      unsigned int i, nbr( sc.nombre() );
      os << "Valeurs : ";
      for ( i = 0; i < nbr; i++ )
	os << sc.valeur( i ) << ", ";
      os << ", Code : " << sc.code() << ", "
	 << sc.message();
    }
  return os;
}
